package com.kang.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.kang.dto.HotWord;
import com.kang.dto.RecommendDto;
import com.kang.entity.*;
import com.kang.mapper.*;
import com.kang.service.EssayService;
import com.kang.util.Recommend;
import com.kang.util.ThreadLocalUtil;
import com.kang.vo.ParamInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

import static com.kang.service.impl.BookMarkServiceImpl.getEssayPage;


@Service
public class EssayServiceImpl extends ServiceImpl<EssayMapper,Essay> implements EssayService {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private EssayMapper essayMapper;

    @Autowired
    private LikeMapper likeMapper;

    @Autowired
    private BookMarkMapper bookMarkMapper;

    @Autowired
    private LabelMapper labelMapper;

    @Autowired
    private ConcernMapper concernMapper;

    @Autowired
    private UserMapper userMapper;


    @Override
    public Page<Essay> getEssayList(ParamInfo paramInfo) {
        Page<Essay> page = new Page<>(paramInfo.getPageNum(),paramInfo.getPageSize());
        QueryWrapper<Essay> wrapper = new QueryWrapper<>();
        wrapper.like(!StringUtils.isEmpty(paramInfo.getName()),"title",paramInfo.getName());
        wrapper.eq(!StringUtils.isEmpty(paramInfo.getStatus()),"user_id",ThreadLocalUtil.getCurrentUser().getId());
        if (paramInfo.getType() != null) {
            wrapper.eq(paramInfo.getType() == 1,"park_id",0);
        }
        if (paramInfo.getParkId() != null) {
            wrapper.eq(paramInfo.getParkId() != null,"park_id",paramInfo.getParkId());
        }
        wrapper.last("order by create_time desc");
        Page<Essay> essayPage = essayMapper.selectPage(page, wrapper);
        List<Integer> userIdList = essayPage.getRecords().stream().map(Essay::getUserId).collect(Collectors.toList());
        if (userIdList.size() != 0) {
            List<SysUser> userList = userMapper.selectList(new QueryWrapper<SysUser>().in("id", userIdList));
            essayPage.getRecords().forEach(v -> {
                for (SysUser user : userList) {
                    if (v.getUserId().equals(user.getId())) {
                        v.setUsername(user.getUsername());
                        v.setHeadUrl(user.getHeadUrl());
                    }
                }
                if (v.getPhotoUrl() != null) {
                    List<String> collect = Arrays.stream(v.getPhotoUrl().split(",")).collect(Collectors.toList());
                    v.setPhotoUrl(collect.get(0));
                }
            });
        }
        return essayPage(essayPage);
    }

    public Page<Essay> essayPage(Page<Essay> essayPage) {
        return getEssayPage(essayPage, stringRedisTemplate);
    }

    @Override
    public Essay getEssayById(Integer id) {
        Essay essay = essayMapper.selectById(id);
        //redis中存的浏览量加1
        if (!essay.getUserId().equals(ThreadLocalUtil.getCurrentUser().getId())) {
            stringRedisTemplate.opsForValue().increment("user:view:" + id);
        }
        String viewNum = stringRedisTemplate.opsForValue().get("user:view:" + id);
        String bookMark = stringRedisTemplate.opsForValue().get("user:bookMark:" + id);
        String reply = stringRedisTemplate.opsForValue().get("user:reply:" + id);
        String like = stringRedisTemplate.opsForValue().get("user:like:" + id);
        assert viewNum != null;
        essay.setViewNum(Integer.valueOf(viewNum));
        assert bookMark != null;
        essay.setFavorNum(Integer.valueOf(bookMark));
        assert reply != null;
        essay.setReplayNum(Integer.valueOf(reply));
        assert like != null;
        essay.setClickNum(Integer.valueOf(like));
        //查询是否收藏
        QueryWrapper<BookMark> bookMarkWrapper = new QueryWrapper<>();
        bookMarkWrapper.eq("essay_id",id).eq("user_id",ThreadLocalUtil.getCurrentUser().getId());
        essay.setIfBookMark(bookMarkMapper.selectCount(bookMarkWrapper) == 0 ? 0 : 1);
        //查询是否点赞
        QueryWrapper<Like> likeWrapper = new QueryWrapper<>();
        likeWrapper.eq("essay_id",id).eq("user_id",ThreadLocalUtil.getCurrentUser().getId());
        essay.setIfLike(likeMapper.selectCount(likeWrapper) == 0 ? 0 : 1);
        //添加昵称和头像
        SysUser user = userMapper.selectById(essay.getUserId());
        essay.setUsername(user.getUsername());
        essay.setHeadUrl(user.getHeadUrl());
        //是否关注
        Integer count = concernMapper.selectCount(new QueryWrapper<Concern>().eq("user_id", ThreadLocalUtil.getCurrentUser().getId()).eq("concern_id", essay.getUserId()));
        if (count > 0) {
            essay.setIfConcern(1);
        }
        //  查询标签名称
        if (essay.getLabelId() != null) {
            List<String> labelIdList = Arrays.stream(essay.getLabelId().split(",")).collect(Collectors.toList());
            QueryWrapper<Label> labelWrapper = new QueryWrapper<>();
            labelWrapper.in("id",labelIdList);
            List<String> labelNames = labelMapper.selectList(labelWrapper).stream().map(Label::getLabelName).collect(Collectors.toList());
            essay.setLabelNames(labelNames);
        }

        //统计图片路径
        List<String> collect = Arrays.stream(essay.getPhotoUrl().split(",")).collect(Collectors.toList());
        essay.setUrlList(collect);

        //统计热榜
        stringRedisTemplate.opsForZSet().incrementScore("hotWord", String.valueOf(id), 1); // 加入排序set

        return essay;
    }


    @Override
    public Integer insertEssay(Essay essay) {
        essay.setCreateTime(new Date());
        essay.setUpdateTime(new Date());
        essay.setViewNum(0);
        essay.setReplayNum(0);
        essay.setFavorNum(0);
        essay.setClickNum(0);
        essay.setParkId(essay.getParkId() != null ? essay.getParkId() : 0);
        essay.setCreateBy(ThreadLocalUtil.getCurrentUser().getUsername());
        essay.setUserId(ThreadLocalUtil.getCurrentUser().getId());

        int insert = essayMapper.insert(essay);
        if (insert == 1) {
            stringRedisTemplate.opsForValue().set("user:view:" + essay.getId(), String.valueOf(0));
            stringRedisTemplate.opsForValue().set("user:bookMark:" + essay.getId(), String.valueOf(0));
            stringRedisTemplate.opsForValue().set("user:like:" + essay.getId(), String.valueOf(0));
            stringRedisTemplate.opsForValue().set("user:reply:" + essay.getId(), String.valueOf(0));
        }
        return insert;

    }

    @Override
    public Integer deleteEssay(Integer id) {
        int i = baseMapper.deleteById(id);
        if (i == 1) {
            stringRedisTemplate.delete("user:view:" + id);
            stringRedisTemplate.delete("user:bookMark:" + id);
            stringRedisTemplate.delete("user:like:" + id);
            stringRedisTemplate.delete("user:reply:" + id);
        }
        return i;
    }

    @Override
    public List<Essay> getRecommendEssay() {
        Integer userId = ThreadLocalUtil.getCurrentUser().getId();
        //第一个参数的所有文章id
        List<Integer> essayIdList = getEssayIdList(userId);
        RecommendDto recommendDto = new RecommendDto();
        List<Essay> essList = essayMapper.selectList(new QueryWrapper<Essay>().in("id", essayIdList));
        recommendDto.setUserLikeEssayIdList(essList);
        //第二个参数
        ArrayList<RecommendDto> arrayList = new ArrayList<>();
        //获取用户关注的用户
        List<Concern> concernList = concernMapper.selectList(new QueryWrapper<Concern>().eq("user_id", userId));
        List<Integer> concernIdList = concernList.stream().map(Concern::getConcernId).collect(Collectors.toList());
        //index用作唯一标识
        int index = 1;
        for (Integer integer : concernIdList) {
            RecommendDto recommendDto1 = new RecommendDto();
            List<Integer> integerList = getEssayIdList(integer);
            List<Essay> essayList = essayMapper.selectList(new QueryWrapper<Essay>().in(integerList.size() != 0,"id", integerList));
            recommendDto1.setMarkUserLikeEssayList(essayList);
//            int sum = essayList.stream().mapToInt(Essay::getClickNum).sum() + essayList.stream().mapToInt(Essay::getFavorNum).sum();
            recommendDto1.setStatus(index++);
            arrayList.add(recommendDto1);
        }
        //去重后的第二个参数
        List<RecommendDto> dtoList = arrayList.stream().distinct().collect(Collectors.toList());
        //获取推荐文章id
        Recommend recommend = new Recommend();
        List<Integer> essayListId = recommend.recommend(recommendDto, dtoList);
        List<Essay> resultList = new ArrayList<>();
        if (essayListId != null) {
            //不查询社区文章
            List<Essay> essayList = essayMapper.selectList(new QueryWrapper<Essay>().in("id", essayListId).eq("park_id",0));
            resultList.addAll(essayList);
        }
        //判断文章是否够五条前端展示
        List<Essay> list = new ArrayList<>();
        resultList.forEach(v -> {
            if (!v.getUserId().equals(userId)) {
                list.add(v);
            }
        });
        List<Essay> collect = new ArrayList<>();
        if (list.size() < 5) {
            collect = essayMapper.selectList(new QueryWrapper<Essay>().notIn("id",essayListId).last("limit " + (int) (1 + Math.random() * 10) + ", 50"));
        }
        Collections.shuffle(collect);
        list.addAll(collect);
        return list;
    }

    @Override
    public Page<Essay> getRecommendPage(ParamInfo paramInfo) {
        Page<Essay> page = new Page<>(paramInfo.getPageNum(), paramInfo.getPageSize());
        Integer userId = ThreadLocalUtil.getCurrentUser().getId();
        //第一个参数的所有文章id
        List<Integer> essayIdList = getEssayIdList(userId);
        RecommendDto recommendDto = new RecommendDto();
        List<Essay> essList = essayMapper.selectList(new QueryWrapper<Essay>().in("id", essayIdList));
        recommendDto.setUserLikeEssayIdList(essList);
        //第二个参数
        ArrayList<RecommendDto> arrayList = new ArrayList<>();
        //获取用户关注的用户
        List<Concern> concernList = concernMapper.selectList(new QueryWrapper<Concern>().eq("user_id", userId));
        List<Integer> concernIdList = concernList.stream().map(Concern::getConcernId).collect(Collectors.toList());
        //index用作唯一标识
        int index = 1;
        for (Integer integer : concernIdList) {
            RecommendDto recommendDto1 = new RecommendDto();
            List<Integer> integerList = getEssayIdList(integer);
            List<Essay> essayList = essayMapper.selectList(new QueryWrapper<Essay>().in(integerList.size() != 0,"id", integerList));
            recommendDto1.setMarkUserLikeEssayList(essayList);
//            int sum = essayList.stream().mapToInt(Essay::getClickNum).sum() + essayList.stream().mapToInt(Essay::getFavorNum).sum();
            recommendDto1.setStatus(index++);
            arrayList.add(recommendDto1);
        }
        //去重后的第二个参数
        List<RecommendDto> dtoList = arrayList.stream().distinct().collect(Collectors.toList());
        //获取推荐文章id
        List<Integer> essayListId = new ArrayList<>();
        Recommend recommend = new Recommend();
        for (RecommendDto dto : dtoList) {
            List<RecommendDto> dtos = new ArrayList<>();
            dtos.add(dto);
            List<Integer> ids = recommend.recommend(recommendDto, dtos);
            essayListId.addAll(ids);
        }
        List<Integer> repIdList = essayListId.stream().distinct().collect(Collectors.toList());

        //不查询社区文章
//        List<Essay> essayList = essayMapper.selectList(new QueryWrapper<Essay>().in("id", repIdList).eq("park_id",0));
//        List<Essay> resultList = new ArrayList<>(essayList);
        //判断文章是否够五条前端展示
//        List<Integer> collect = new ArrayList<>();
//        if (repIdList.size() < 5) {
//            collect = essayMapper.selectList(new QueryWrapper<Essay>().notIn("id",repIdList).last("limit " + (int) (1 + Math.random() * 10) + ", 10")).stream().map(Essay::getId).collect(Collectors.toList());
//        }
//        repIdList.addAll(collect);
        Page<Essay> essayPage = essayMapper.selectPage(page, new QueryWrapper<Essay>().in("id", repIdList));
        List<Essay> list = new ArrayList<>();
        essayPage.getRecords().forEach(v -> {
            if (!v.getUserId().equals(userId)) {
                list.add(v);
            }
        });
        essayPage.setRecords(list);
        essayPage.setTotal(list.size());
        return essayPage(essayPage);
    }

    @Override
    public List<Essay> getHotEssay() {
        List<Integer> idList = new ArrayList<>();
        Set<ZSetOperations.TypedTuple<String>> typedTuples = stringRedisTemplate.opsForZSet().reverseRangeByScoreWithScores("hotWord", 1, 10000);
        assert typedTuples != null;
        Iterator<ZSetOperations.TypedTuple<String>> iterator = typedTuples.iterator();
        int flag = 0;
        while (iterator.hasNext()){
            flag++;
            ZSetOperations.TypedTuple<String> typedTuple = iterator.next();
            String value = typedTuple.getValue();
            assert value != null;
            idList.add(Integer.valueOf(value));
            if ( flag >= 10 ) break;
        }
        List<Essay> list = new ArrayList<>();
        for (Integer integer : idList) {
            Essay essay = essayMapper.selectById(integer);
            if (essay.getTitle().length() >= 50) {
                essay.setTitle(essay.getTitle().substring(0,50));
            }
            list.add(essay);
        }

        return list;
    }

    public List<Integer> getEssayIdList(Integer id) {
        //获取当前用户所喜欢以及收藏的文章
        List<Like> userLike = likeMapper.selectList(new QueryWrapper<Like>().eq("user_id",id));
        List<BookMark> userMark = bookMarkMapper.selectList(new QueryWrapper<BookMark>().eq("user_id",id));
        //所有文章的id
        List<Integer> arrayList = new ArrayList<>();
        arrayList.addAll(userLike.stream().map(Like::getEssayId).collect(Collectors.toList()));
        arrayList.addAll(userMark.stream().map(BookMark::getEssayId).collect(Collectors.toList()));
        //获取去重后的喜欢和收藏文章id
        return arrayList.stream().distinct().collect(Collectors.toList());
    }
}
